package com.tianjin.weight.shiro;

import com.tianjin.weight.constants.Constant;
import com.tianjin.weight.utils.JwtTokenUtil;
import com.tianjin.weight.utils.ServiceBeanUtils;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;

import java.util.Collection;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Slf4j
public class CustomRealm extends AuthorizingRealm {
    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof CustomPasswordToken;
    }

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        SimpleAuthorizationInfo authorizationInfo=new SimpleAuthorizationInfo();
        String accessToken= (String) SecurityUtils.getSubject().getPrincipal();
        Long userId= JwtTokenUtil.getUserId(accessToken);
        log.info("userId={}",userId);

        if(ServiceBeanUtils.getRedisService().hasKey(Constant.JWT_REFRESH_KEY+userId)&&ServiceBeanUtils.getRedisService().getExpire(Constant.JWT_REFRESH_KEY+userId, TimeUnit.MILLISECONDS)>JwtTokenUtil.getRemainingTime(accessToken)){
            List<String> roleNames= null;
            try {
                roleNames = ServiceBeanUtils.getRoleService().getRoleNames(userId);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
            if(roleNames!=null&&!roleNames.isEmpty()){
                try {
                    authorizationInfo.addRoles(ServiceBeanUtils.getRoleService().getRoleNames(userId));
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            }
            try {
                authorizationInfo.setStringPermissions(ServiceBeanUtils.getPermissionService().getPermissionsByUserId(userId));
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }else {
            Claims claimsFromToken = JwtTokenUtil.getClaimsFromToken(accessToken);
            if(claimsFromToken.get(Constant.JWT_ROLES_KEY)!=null){
                authorizationInfo.addRoles((Collection<String>) claimsFromToken.get(Constant.JWT_ROLES_KEY));
            }
            if(claimsFromToken.get(Constant.JWT_PERMISSIONS_KEY)!=null){
                authorizationInfo.addStringPermissions((Collection<String>) claimsFromToken.get(Constant.JWT_PERMISSIONS_KEY));
            }

        }
        return authorizationInfo;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        CustomPasswordToken token= (CustomPasswordToken) authenticationToken;
        SimpleAuthenticationInfo simpleAuthenticationInfo=new SimpleAuthenticationInfo(token.getPrincipal(),token.getPrincipal(),getName());
        return simpleAuthenticationInfo;
    }
}
